/*
 * file.c
 *
 *  Created on: Dec 15, 2008
 *      Author: michael
 */

#include<comlib.h>

/****
 * read file
 * nFile the file descripter
 * pData read the data to the mem address of pData
 * pSize how many size read (back the actual read count)
 ***/
int ReadFile(int nFile, void *pData, int *pSize)
{
	int nLeft, nRead;
	ASSERT(pData!=NULL&&pSize!=NULL);
	char *pcData = pData;
	nLeft = *pSize;

	while (nLeft > 0)
	{
		if ((nRead = read(nFile, pcData, nLeft)) < 0)
		{
			if (errno != EINTR)
			{
				ASSERT(0)
			}
			nRead = 0;
		} else if (nRead == 0)
			break;
		nLeft -= nRead;
		pcData += nRead;
	}

	*pSize = *pSize - nLeft;
	return 0;
}

/****
 * write data to file
 * nFile file descripter
 * pData data ready to write
 * nSize how many data will be write
 ***/
int WriteFile(int nFile, void *pData, int nSize)
{
	int nLeft = nSize, nWrite;
	const char *pcData = pData;
	ASSERT(pcData!=NULL);
	while (nLeft > 0)
	{
		if ((nWrite = write(nFile, pcData, nLeft)) <= 0)
		{
			if (errno != EINTR)
			{
				ASSERT(0)
			}
			nWrite = 0;
		}
		nLeft -= nWrite;
		pcData += nWrite;
	}
	return 0;
}

/****
 * read file with timeout
 * nFile file descripter
 * pData data read from file to addr pData
 * pnSize how manySize data be read
 * nTimeout read file timeout
 * return 1 timeout 0 success other error
 ***/
int ReadFileTime(int nFile, void *pData, int *pnSize, int nTimeout)
{
	int nLeft, nRead;
	int nUseTime = 0;
	time_t t1, t2;
	char *pcData;
	int nFlag;
	fd_set fdsRead;
	struct timeval tval;
	pcData = pData;
	ASSERT(pData!=NULL&&pnSize!=NULL);
	nLeft = *pnSize;
	while (nLeft > 0)
	{
		if (nTimeout != 0)
			nTimeout -= nUseTime;
		FD_ZERO(&fdsRead);
		FD_SET(nFile,&fdsRead);
		tval.tv_sec = nTimeout;
		tval.tv_usec = 0;

		t1 = 0;
		t2 = 0;

		time(&t1);
		nFlag = select(nFile + 1, &fdsRead, NULL, NULL, &tval);
		if (nFlag == 0) //timeout
		{
			*pnSize -= nLeft;
			ASSERTEXT(0,1);
		}
		if (nFlag < 0) //error
		{
			if (errno != EINTR)
				ASSERT(0)
			else
			{
				nRead = 0;
				time(&t2);
				nUseTime = t2 - t1;
			}
		} else // read data
		{
			time(&t2);
			nUseTime = t2 - t1;
			if ((nRead = read(nFile, pcData, nLeft)) < 0)
			{
				if (errno != EINTR)
				{
					ASSERT(0)
				}
				nRead = 0;
			} else if (nRead == 0)
				break;
		}
		nLeft -= nRead;
		pcData += nRead;
	}
	*pnSize -= nLeft;
	return 0;
}

/****
 * Write file with timeout
 * nFile file descripter
 * pData the data ready to write
 * nSize how many data to be write
 * nTimeout timeout
 ***/
int WriteFileTime(int nFile, void *pData, int nSize, int nTimeout)
{
	int nLeft, nWrite;
	int nUseTime = 0;
	time_t t1, t2;
	char *pcData;
	int nFlag;
	fd_set fdsWrite;
	struct timeval tval;
	pcData = pData;
	ASSERT(pData!=NULL);
	nLeft = nSize;
	while (nLeft > 0)
	{
		if (nTimeout != 0)
			nTimeout -= nUseTime;
		FD_ZERO(&fdsWrite);
		FD_SET(nFile,&fdsWrite);
		tval.tv_sec = nTimeout;
		tval.tv_usec = 0;

		t1 = 0;
		t2 = 0;

		time(&t1);
		nFlag = select(nFile + 1, NULL, &fdsWrite, NULL, &tval);
		if (nFlag == 0) //timeout
		{
			ASSERTEXT(0,1);
		}
		if (nFlag < 0) //error
		{
			if (errno != EINTR)
				ASSERT(0)
			else
			{
				nWrite = 0;
				time(&t2);
				nUseTime = t2 - t1;
			}
		} else // read data
		{
			time(&t2);
			nUseTime = t2 - t1;
			if ((nWrite = write(nFile, pcData, nLeft)) <= 0)
			{
				if (errno != EINTR)
				{
					ASSERT(0)
				}
				nWrite = 0;
			}
		}
		nLeft -= nWrite;
		pcData += nWrite;
	}
	return 0;
}
